package org.tool.reflect;

import org.tool.TipException;
import org.tool.core.lang.Assert;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * 注解相关工具类
 *
 * @author 李坤
 * @date 2022/4/26 19:41
 */
public abstract class AnnotationUtil {

    /**
     * 解析给定的注解 {@code annotation} 并将其值填充到 {@code instance} 对象中
     *
     * @param instance   将要填充的对象
     * @param annotation 要解析的注解
     * @param <T>        泛型
     *
     * @return 返回填充后的对象
     */
    public static <T> void parseAnnotation2FillInstance(T instance, Annotation annotation) {
        if (Objects.nonNull(annotation) && Objects.nonNull(instance)) {
            for (Method method : annotation.annotationType().getDeclaredMethods()) {
                try {
                    JavaBeanUtil.setBeanProperty(method.getName(), method.invoke(annotation), instance);
                } catch (IllegalAccessException | InvocationTargetException exception) {
                    throw new TipException(String.format("解析注解 %s 并填充到对象 %s 失败", annotation, instance));
                }
            }
        }
    }

    /**
     * 解析给定的注解 {@code annotation} 并将其值填充到 {@code clazz} 类实例化的对象
     *
     * @param clazz      将要实例化的类
     * @param annotation 要解析的注解
     * @param <T>        泛型
     *
     * @return 返回实例化的对象
     */
    public static <T> T parseAnnotation2InstantiatedClass(Class<T> clazz, Annotation annotation) {
        Assert.notNull(clazz, "clazz 不能为空");

        T instance = null;

        // 如果给定的注解不为空，则实例化并填充对应的对象
        if (Objects.nonNull(annotation)) {
            // 实例化给定类型的对象
            instance = ConstructorUtil.newInstance(clazz);
            // 解析注解值并填充到实例化对象的属性中
            parseAnnotation2FillInstance(instance, annotation);
        }
        return instance;
    }

}
